package com.example.demo;

import com.example.demo.handler.HttpHandler;
import com.example.demo.handler.WebsocketHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;


@Component
public class ChatServer {



    //对服务端进行端口绑定
    @PostConstruct
    public void bind(){
        //创建接受连接线程组
        EventLoopGroup accept = new NioEventLoopGroup();

        //创建处理消息的线程组
        EventLoopGroup work = new NioEventLoopGroup();
        try{
            //netty启动辅助类,将两个nio线程传入
            ServerBootstrap sb = new ServerBootstrap();
            sb.group(accept,work)
                    .option(ChannelOption.SO_BACKLOG,1024)
                    .channel(NioServerSocketChannel.class)
                    //设置绑定io事件的处理类
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            //支持http协议，加入http编解码器的处理类
                            socketChannel.pipeline().addLast(new HttpServerCodec());
                            //将htpp请求封装成fullhttprequest
                            socketChannel.pipeline().addLast(new HttpObjectAggregator(1024*64));
                            //处理文件流
                            socketChannel.pipeline().addLast(new ChunkedWriteHandler());
                            //进行http请求的处理类
                            socketChannel.pipeline().addLast(new HttpHandler());

                            //增加websocket协议编解码
                            socketChannel.pipeline().addLast(new WebSocketServerProtocolHandler("/im"));
                            //增加websocket处理类
                            socketChannel.pipeline().addLast(new WebsocketHandler());
                        }
                    });
            //绑定端口，同步等待成功，sync（）同步阻塞方法，等待bind操作完成才继续。
            ChannelFuture cf = sb.bind(8081).sync();
            System.out.println("服务端启动在"+8081+"端口。");
            //等待服务端监听端口关闭
            cf.channel().closeFuture().sync();
        } catch (Exception e){
            //优雅退出，释放线程池资源
            accept.shutdownGracefully();
            work.shutdownGracefully();
        } finally {
            //优雅退出，释放线程池资源
            accept.shutdownGracefully();
            work.shutdownGracefully();
        }
    }
}
